﻿//NorManager - OpenTTD Dedicated server manager
//Copyright (C) 2014 Tomáš Bosek

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Threading;

namespace NorManager
{
    delegate void CrashObserverHandler();
    /// <summary>
    /// Every 1000ms observes(in separate thread) openttd.exe process for crash.
    /// </summary>
    class CrashObserver
    {
        private Thread observerThread = null;
        /// <summary>
        /// Determines "wait" state of observer thread.
        /// True => thread is looking for crash
        /// False => thread is in "wait" state
        /// </summary>
        private bool observe = true;

        /// <summary>
        /// Crash event. It is supposed to be handled in session only. Use SessionStateHandler for Session singleton instead.
        /// </summary>
        internal CrashObserverHandler crashed;
        /// <summary>
        /// Initializes CrashObserver.
        /// </summary>
        internal CrashObserver()
        {
            crashed += new CrashObserverHandler(delegate
            {
                Logger.Instance.Log("Crash detected!");
            });

            observerThread = new Thread(delegate()
            {
                try
                {
                    while (true)
                    {
                        if (observe && Session.Instance.SessionProc != null && Session.Instance.SessionProc.HasExited)
                        {
                            observe = false;
                            crashed();
                        }
                        Thread.Sleep(1000);
                    }
                }
                catch (ThreadInterruptedException) { }
            });
        }
        /// <summary>
        /// Starts/continues CrashObserver
        /// CrashObserver pauses himself on crash event call. You just have to re/start it!
        /// </summary>
        internal void Start()
        {
            if (observerThread != null)
            {
                if (!observerThread.IsAlive)
                    observerThread.Start();     //Start new thread!
                else
                    observe = true;     //Continue thread. Look for crash!
            }
            else
                Logger.Instance.Log("Unable to start new observer thread.");
        }
        /// <summary>
        /// Manually stops observer. It can be later resumed again with Start method.
        /// </summary>
        internal void Stop()
        {
            observe = false;
        }
    }
}
